home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / sh.sem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-17  |  19.5 KB  |  794 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.sem.c,v 3.3 1991/07/23 23:20:08 christos Exp $ */
  2. /*
  3.  * sh.sem.c: I/O redirections and job forking. A touchy issue!
  4.  *         Most stuff with builtins is incorrect
  5.  */
  6. /*-
  7.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  8.  * All rights reserved.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38. #include "config.h"
  39. RCSID("$Id: sh.sem.c,v 3.3 1991/07/23 23:20:08 christos Exp $")
  40.  
  41. #include "sh.h"
  42. #include "tc.h"
  43.  
  44. #ifdef FIOCLEX
  45. # ifndef sun
  46. #  ifndef CLEX_DUPS
  47. #   define CLEX_DUPS
  48. #  endif /* CLEX_DUPS */
  49. # endif /* sun */
  50. #endif /* FIOCLEX */
  51.  
  52. #ifdef sparc
  53. # include <vfork.h>
  54. #endif /* sparc */
  55.  
  56. #ifdef VFORK
  57. static    sigret_t    vffree    __P((int));
  58. #endif 
  59. static    void        doio    __P((struct command *, int *, int *));
  60. static    void        chkclob    __P((char *));
  61.  
  62. /*
  63.  * C shell
  64.  */
  65. /*VARARGS 1*/
  66. void
  67. execute(t, wanttty, pipein, pipeout)
  68.     register struct command *t;
  69.     int     wanttty, *pipein, *pipeout;
  70. {
  71. #if defined(convex) || defined(__convex__)
  72.     extern bool use_fork;    /* use fork() instead of vfork()? */
  73. #endif 
  74.  
  75.     bool    forked = 0;
  76.     struct biltins *bifunc;
  77.     int     pid = 0;
  78.     int     pv[2];
  79.  
  80. #ifdef BSDSIGS
  81.     static sigmask_t csigmask;
  82. # ifdef VFORK
  83.     static sigmask_t ocsigmask;
  84. # endif /* VFORK */
  85. #endif /* BSDSIGS */
  86. #ifdef VFORK
  87.     static int onosigchld = 0;
  88. #endif /* VFORK */
  89.     static int nosigchld = 0;
  90.  
  91.     if (t == 0)
  92.     return;
  93.     /*
  94.      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
  95.      * Don't check for wantty > 0...
  96.      */
  97.     if (t->t_dflg & F_AMPERSAND)
  98.     wanttty = 0;
  99.     switch (t->t_dtyp) {
  100.  
  101.     case NODE_COMMAND:
  102.     if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
  103.         (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
  104.     if ((t->t_dflg & F_REPEAT) == 0)
  105.         Dfix(t);        /* $ " ' \ */
  106.     if (t->t_dcom[0] == 0)
  107.         return;
  108.     /* fall into... */
  109.  
  110.     case NODE_PAREN:
  111.     if (t->t_dflg & F_PIPEOUT)
  112.         mypipe(pipeout);
  113.     /*
  114.      * Must do << early so parent will know where input pointer should be.
  115.      * If noexec then this is all we do.
  116.      */
  117.     if (t->t_dflg & F_READ) {
  118.         (void) close(0);
  119.         heredoc(t->t_dlef);
  120.         if (noexec)
  121.         (void) close(0);
  122.     }
  123.     if (noexec)
  124.         break;
  125.  
  126.     set(STRstatus, Strsave(STR0));
  127.  
  128.     /*
  129.      * This mess is the necessary kludge to handle the prefix builtins:
  130.      * nice, nohup, time.  These commands can also be used by themselves,
  131.      * and this is not handled here. This will also work when loops are
  132.      * parsed.
  133.      */
  134.     while (t->t_dtyp == NODE_COMMAND)
  135.         if (eq(t->t_dcom[0], STRnice))
  136.         if (t->t_dcom[1])
  137.             if (strchr("+-", t->t_dcom[1][0]))
  138.             if (t->t_dcom[2]) {
  139.                 setname("nice");
  140.                 t->t_nice =
  141.                 getn(t->t_dcom[1]);
  142.                 lshift(t->t_dcom, 2);
  143.                 t->t_dflg |= F_NICE;
  144.             }
  145.             else
  146.                 break;
  147.             else {
  148.             t->t_nice = 4;
  149.             lshift(t->t_dcom, 1);
  150.             t->t_dflg |= F_NICE;
  151.             }
  152.         else
  153.             break;
  154.         else if (eq(t->t_dcom[0], STRnohup))
  155.         if (t->t_dcom[1]) {
  156.             t->t_dflg |= F_NOHUP;
  157.             lshift(t->t_dcom, 1);
  158.         }
  159.         else
  160.             break;
  161.         else if (eq(t->t_dcom[0], STRtime))
  162.         if (t->t_dcom[1]) {
  163.             t->t_dflg |= F_TIME;
  164.             lshift(t->t_dcom, 1);
  165.         }
  166.         else
  167.             break;
  168. #ifdef F_VER
  169.         else if (eq(t->t_dcom[0], STRver))
  170.         if (t->t_dcom[1] && t->t_dcom[2]) {
  171.             setname("ver");
  172.             t->t_systype = getv(t->t_dcom[1]);
  173.             lshift(t->t_dcom, 2);
  174.             t->t_dflg |= F_VER;
  175.         }
  176.         else
  177.             break;
  178. #endif  /* F_VER */
  179.         else
  180.         break;
  181.  
  182.     /* is t a command */
  183.     if (t->t_dtyp == NODE_COMMAND) {
  184.         /*
  185.          * Check if we have a builtin function and remember which one.
  186.          */
  187.         bifunc = isbfunc(t);
  188.     }
  189.     else {            /* not a command */
  190.         bifunc = NULL;
  191.     }
  192.  
  193.     /*
  194.      * We fork only if we are timed, or are not the end of a parenthesized
  195.      * list and not a simple builtin function. Simple meaning one that is
  196.      * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
  197.      * fork in some of these cases.
  198.      */
  199.     /*
  200.      * Prevent forking cd, pushd, popd, chdir cause this will cause the
  201.      * shell not to change dir!
  202.      */
  203.     if (bifunc && (bifunc->bfunct == dochngd ||
  204.                bifunc->bfunct == dopushd ||
  205.                bifunc->bfunct == dopopd))
  206.         t->t_dflg &= ~(F_NICE);
  207.     if (((t->t_dflg & F_TIME) || (t->t_dflg & F_NOFORK) == 0 &&
  208.          (!bifunc || t->t_dflg &
  209.           (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP))) ||
  210.     /*
  211.      * We have to fork for eval too.
  212.      */
  213.         (bifunc && (t->t_dflg & F_PIPEIN) != 0 &&
  214.          bifunc->bfunct == doeval))
  215. #ifdef VFORK
  216.         if (t->t_dtyp == NODE_PAREN ||
  217.         t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc)
  218. #endif /* VFORK */
  219.         {
  220.         forked++;
  221.         /*
  222.          * We need to block SIGCHLD here, so that if the process does
  223.          * not die before we can set the process group
  224.          */
  225.         if (wanttty >= 0 && !nosigchld) {
  226. #ifdef BSDSIGS
  227.             csigmask = sigblock(sigmask(SIGCHLD));
  228. #else /* !BSDSIGS */
  229.             sighold(SIGCHLD);
  230. #endif /* BSDSIGS */
  231.  
  232.             nosigchld = 1;
  233.         }
  234.  
  235.         pid = pfork(t, wanttty);
  236.         if (pid == 0 && nosigchld) {
  237. #ifdef BSDSIGS
  238.             (void) sigsetmask(csigmask);
  239. #else /* !BSDSIGS */
  240.             (void) sigrelse(SIGCHLD);
  241. #endif /* BSDSIGS */
  242.             nosigchld = 0;
  243.         }
  244.         }
  245.  
  246. #ifdef VFORK
  247.         else {
  248.         int     ochild, osetintr, ohaderr, odidfds;
  249.         int     oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
  250.         int     oisoutatty, oisdiagatty;
  251.  
  252. # ifndef FIOCLEX
  253.         int     odidcch;
  254.  
  255. # endif  /* !FIOCLEX */
  256. # ifdef BSDSIGS
  257.         sigmask_t omask;
  258. # endif /* BSDSIGS */
  259.  
  260.         /*
  261.          * Prepare for the vfork by saving everything that the child
  262.          * corrupts before it exec's. Note that in some signal
  263.          * implementations which keep the signal info in user space
  264.          * (e.g. Sun's) it will also be necessary to save and restore
  265.          * the current sigvec's for the signals the child touches
  266.          * before it exec's.
  267.          */
  268. # ifdef BSDSIGS
  269.  
  270.         /*
  271.          * Sooooo true... If this is a Sun, save the sigvec's. (Skip
  272.          * Gilbrech - 11/22/87)
  273.          */
  274. #  ifdef SAVESIGVEC
  275.         sigvec_t savesv[NSIGSAVED];
  276.         sigmask_t savesm;
  277.  
  278. #  endif /* SAVESIGVEC */
  279.         if (wanttty >= 0 && !nosigchld && !noexec) {
  280.             csigmask = sigblock(sigmask(SIGCHLD));
  281.             nosigchld = 1;
  282.         }
  283.         omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT));
  284. # else /* !BSDSIGS */
  285.         (void) sighold(SIGCHLD);
  286.         (void) sighold(SIGINT);
  287. # endif  /* !BSDSIGS */
  288.         ochild = child;
  289.         osetintr = setintr;
  290.         ohaderr = haderr;
  291.         odidfds = didfds;
  292. # ifndef FIOCLEX
  293.         odidcch = didcch;
  294. # endif /* !FIOCLEX */
  295.         oSHIN = SHIN;
  296.         oSHOUT = SHOUT;
  297.         oSHDIAG = SHDIAG;
  298.         oOLDSTD = OLDSTD;
  299.         otpgrp = tpgrp;
  300.         oisoutatty = isoutatty;
  301.         oisdiagatty = isdiagatty;
  302. # ifdef BSDSIGS
  303.         ocsigmask = csigmask;
  304. # endif /* BSDSIGS */
  305.         onosigchld = nosigchld;
  306.         Vsav = Vdp = 0;
  307.         Vexpath = 0;
  308.         Vt = 0;
  309. # ifdef SAVESIGVEC
  310.         savesm = savesigvec(savesv);
  311. # endif /* SAVESIGVEC */
  312. # if defined(convex) || defined(__convex__)
  313.         if (use_fork)
  314.             pid = fork();
  315.         else
  316.             pid = vfork();
  317. # else /* !convex && !__convex__ */
  318.         pid = vfork();
  319. # endif /* convex || __CONVEX__ */
  320.  
  321.         if (pid < 0) {
  322. # ifdef BSDSIGS
  323. #  ifdef SAVESIGVEC
  324.             restoresigvec(savesv, savesm);
  325. #  endif /* SAVESIGVEC */
  326.             (void) sigsetmask(omask);
  327. # else /* !BSDSIGS */
  328.             (void) sigrelse(SIGCHLD);
  329.             (void) sigrelse(SIGINT);
  330. #endif  /* BSDSIGS */
  331.             stderror(ERR_NOPROC);
  332.         }
  333.         forked++;
  334.         if (pid) {    /* parent */
  335. # ifdef BSDSIGS
  336. #  ifdef SAVESIGVEC
  337.             restoresigvec(savesv, savesm);
  338. #  endif /* SAVESIGVEC */
  339. # endif /* BSDSIGS */
  340.             child = ochild;
  341.             setintr = osetintr;
  342.             haderr = ohaderr;
  343.             didfds = odidfds;
  344.             SHIN = oSHIN;
  345. # ifndef FIOCLEX
  346.             didcch = odidcch;
  347. # endif /* !FIOCLEX */
  348.             SHOUT = oSHOUT;
  349.             SHDIAG = oSHDIAG;
  350.             OLDSTD = oOLDSTD;
  351.             tpgrp = otpgrp;
  352.             isoutatty = oisoutatty;
  353.             isdiagatty = oisdiagatty;
  354. # ifdef BSDSIGS
  355.             csigmask = ocsigmask;
  356. # endif /* BSDSIGS */
  357.             nosigchld = onosigchld;
  358.  
  359.             xfree((ptr_t) Vsav);
  360.             Vsav = 0;
  361.             xfree((ptr_t) Vdp);
  362.             Vdp = 0;
  363.             xfree((ptr_t) Vexpath);
  364.             Vexpath = 0;
  365.             blkfree((Char **) Vt);
  366.             Vt = 0;
  367.             /* this is from pfork() */
  368.             palloc(pid, t);
  369. # ifdef BSDSIGS
  370.             (void) sigsetmask(omask);
  371. # else /* !BSDSIGS */
  372.             (void) sigrelse(SIGCHLD);
  373.             (void) sigrelse(SIGINT);
  374. # endif  /* BSDSIGS */
  375.         }
  376.         else {        /* child */
  377.             /* this is from pfork() */
  378.             int     pgrp;
  379.             bool    ignint = 0;
  380.  
  381.             if (nosigchld) {
  382. # ifdef BSDSIGS
  383.             (void) sigsetmask(csigmask);
  384. # else /* !BSDSIGS */
  385.             (void) sigrelse(SIGCHLD);
  386. # endif /* BSDSIGS */
  387.             nosigchld = 0;
  388.             }
  389.  
  390.             if (setintr)
  391.             ignint =
  392.                 (tpgrp == -1 &&
  393.                  (t->t_dflg & F_NOINTERRUPT))
  394.                 || gointr && eq(gointr, STRminus);
  395.             pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
  396.             child++;
  397.             if (setintr) {
  398.             setintr = 0;
  399. # ifdef notdef
  400.             (void) signal(SIGCHLD, SIG_DFL);
  401. # endif 
  402. /*
  403.  * casts made right for SunOS 4.0 by Douglas C. Schmidt
  404.  * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU>
  405.  * (thanks! -- PWP)
  406.  *
  407.  * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET>
  408.  * (thanks again)
  409.  */
  410.             if (ignint) {
  411.                 (void) signal(SIGINT, SIG_IGN);
  412.                 (void) signal(SIGQUIT, SIG_IGN);
  413.             }
  414.             else {
  415.                 (void) signal(SIGINT,  vffree);
  416.                 (void) signal(SIGQUIT, SIG_DFL);
  417.             }
  418.  
  419.             if (wanttty >= 0) {
  420. #ifdef __MINT__
  421.             /* see sh.proc.c */
  422.                 extern void sig_tmp_ign();
  423.  
  424.                 (void) signal(SIGTSTP, sig_tmp_ign);
  425.                 (void) signal(SIGTTIN, sig_tmp_ign);
  426.                 (void) signal(SIGTTOU, sig_tmp_ign);
  427. #else
  428.                 (void) signal(SIGTSTP, SIG_DFL);
  429.                 (void) signal(SIGTTIN, SIG_DFL);
  430.                 (void) signal(SIGTTOU, SIG_DFL);
  431. #endif
  432.             }
  433.  
  434.             (void) signal(SIGTERM, parterm);
  435.             }
  436.             else if (tpgrp == -1 &&
  437.                  (t->t_dflg & F_NOINTERRUPT)) {
  438.             (void) signal(SIGINT, SIG_IGN);
  439.             (void) signal(SIGQUIT, SIG_IGN);
  440.             }
  441.  
  442. # ifdef _SEQUENT_
  443.             pgetty(wanttty ? wanttty : 1, pgrp);
  444. # else /* _SEQUENT_ */
  445.             pgetty(wanttty, pgrp);
  446. # endif /* _SEQUENT_ */
  447.  
  448.             if (t->t_dflg & F_NOHUP)
  449.             (void) signal(SIGHUP, SIG_IGN);
  450.             if (t->t_dflg & F_NICE)
  451. # ifdef BSDNICE
  452.             (void) setpriority(PRIO_PROCESS,
  453.                        0, t->t_nice);
  454. # else /* !BSDNICE */
  455.             (void) nice(t->t_nice);
  456. # endif /* BSDNICE */
  457. # ifdef F_VER
  458.             if (t->t_dflg & F_VER) {
  459.             Setenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
  460.             dohash(NULL, NULL);
  461.             }
  462. # endif /* F_VER */
  463.         }
  464.  
  465.         }
  466. #endif /* VFORK */
  467.     if (pid != 0) {
  468.         /*
  469.          * It would be better if we could wait for the whole job when we
  470.          * knew the last process had been started.  Pwait, in fact, does
  471.          * wait for the whole job anyway, but this test doesn't really
  472.          * express our intentions.
  473.          */
  474.         if (didfds == 0 && t->t_dflg & F_PIPEIN) {
  475.         (void) close(pipein[0]);
  476.         (void) close(pipein[1]);
  477.         }
  478.         if ((t->t_dflg & F_PIPEOUT) == 0) {
  479.         if (nosigchld) {
  480. #ifdef BSDSIGS
  481.             (void) sigsetmask(csigmask);
  482. #else /* !BSDSIGS */
  483.             (void) sigrelse(SIGCHLD);
  484. #endif /* BSDSIGS */
  485.             nosigchld = 0;
  486.         }
  487.         if ((t->t_dflg & F_AMPERSAND) == 0)
  488.             pwait();
  489.         }
  490.         break;
  491.     }
  492.     doio(t, pipein, pipeout);
  493.     if (t->t_dflg & F_PIPEOUT) {
  494.         (void) close(pipeout[0]);
  495.         (void) close(pipeout[1]);
  496.     }
  497.     /*
  498.      * Perform a builtin function. If we are not forked, arrange for
  499.      * possible stopping
  500.      */
  501.     if (bifunc) {
  502.         func(t, bifunc);
  503.         if (forked)
  504.         exitstat();
  505.         break;
  506.     }
  507.     if (t->t_dtyp != NODE_PAREN) {
  508.         doexec(t);
  509.         /* NOTREACHED */
  510.     }
  511.     /*
  512.      * For () commands must put new 0,1,2 in FSH* and recurse
  513.      */
  514.     OLDSTD = dcopy(0, FOLDSTD);
  515.     SHOUT = dcopy(1, FSHOUT);
  516.     isoutatty = isatty(SHOUT);
  517.     SHDIAG = dcopy(2, FSHDIAG);
  518.     isdiagatty = isatty(SHDIAG);
  519.     (void) close(SHIN);
  520.     SHIN = -1;
  521. #ifndef FIOCLEX
  522.     didcch = 0;
  523. #endif /* !FIOCLEX */
  524.     didfds = 0;
  525.     wanttty = -1;
  526.     t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
  527.     execute(t->t_dspr, wanttty, NULL, NULL);
  528.     exitstat();
  529.  
  530.     case NODE_PIPE:
  531.     t->t_dcar->t_dflg |= F_PIPEOUT |
  532.         (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
  533.     execute(t->t_dcar, wanttty, pipein, pv);
  534.     t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
  535.             (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
  536. #ifndef __MINT__
  537.     if (wanttty > 0)
  538.         wanttty = 0;    /* got tty already */
  539. #endif
  540.     execute(t->t_dcdr, wanttty, pv, pipeout);
  541.     break;
  542.  
  543.     case NODE_LIST:
  544.     if (t->t_dcar) {
  545.         t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
  546.         execute(t->t_dcar, wanttty, NULL, NULL);
  547.         /*
  548.          * In strange case of A&B make a new job after A
  549.          */
  550.         if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
  551.         (t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
  552.         pendjob();
  553.     }
  554.     if (t->t_dcdr) {
  555.         t->t_dcdr->t_dflg |= t->t_dflg &
  556.         (F_NOFORK | F_NOINTERRUPT);
  557.         execute(t->t_dcdr, wanttty, NULL, NULL);
  558.     }
  559.     break;
  560.  
  561.     case NODE_OR:
  562.     case NODE_AND:
  563.     if (t->t_dcar) {
  564.         t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
  565.         execute(t->t_dcar, wanttty, NULL, NULL);
  566.         if ((getn(value(STRstatus)) == 0) !=
  567.         (t->t_dtyp == NODE_AND))
  568.         return;
  569.     }
  570.     if (t->t_dcdr) {
  571.         t->t_dcdr->t_dflg |= t->t_dflg &
  572.         (F_NOFORK | F_NOINTERRUPT);
  573.         execute(t->t_dcdr, wanttty, NULL, NULL);
  574.     }
  575.     break;
  576.     }
  577.     /*
  578.      * Fall through for all breaks from switch
  579.      * 
  580.      * If there will be no more executions of this command, flush all file
  581.      * descriptors. Places that turn on the F_REPEAT bit are responsible for
  582.      * doing donefds after the last re-execution
  583.      */
  584.     if (didfds && !(t->t_dflg & F_REPEAT))
  585.     donefds();
  586. }
  587.  
  588. #ifdef VFORK
  589. static sigret_t
  590. /*ARGSUSED*/
  591. vffree(snum)
  592. int snum;
  593. {
  594.     register Char **v;
  595.  
  596.     if (v = gargv) {
  597.     gargv = 0;
  598.     xfree((ptr_t) v);
  599.     }
  600.     if (v = pargv) {
  601.     pargv = 0;
  602.     xfree((ptr_t) v);
  603.     }
  604.     _exit(1);
  605. #ifndef SIGVOID
  606.     /*NOTREACHED*/
  607.     return(0);
  608. #endif /* SIGVOID */
  609. }
  610. #endif /* VFORK */
  611.  
  612. /*
  613.  * Perform io redirection.
  614.  * We may or maynot be forked here.
  615.  */
  616. static void
  617. doio(t, pipein, pipeout)
  618.     register struct command *t;
  619.     int    *pipein, *pipeout;
  620. {
  621.     register int fd;
  622.     register Char *cp, *dp;
  623.     register int flags = t->t_dflg;
  624.  
  625.     if (didfds || (flags & F_REPEAT))
  626.     return;
  627.     if ((flags & F_READ) == 0) {/* F_READ already done */
  628.     if (cp = t->t_dlef) {
  629.         char    tmp[MAXPATHLEN+1];
  630.  
  631.         /*
  632.          * so < /dev/std{in,out,err} work
  633.          */
  634.         (void) dcopy(SHIN, 0);
  635.         (void) dcopy(SHOUT, 1);
  636.         (void) dcopy(SHDIAG, 2);
  637.         cp = globone(dp = Dfix1(cp), G_IGNORE);
  638.         (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
  639.         tmp[MAXPATHLEN] = '\0';
  640.         xfree((ptr_t) cp);
  641.         xfree((ptr_t) dp);
  642.         if ((fd = open(tmp, O_RDONLY)) < 0)
  643.         stderror(ERR_SYSTEM, tmp, strerror(errno));
  644.         (void) dmove(fd, 0);
  645.     }
  646.     else if (flags & F_PIPEIN) {
  647. #ifdef __MINT__
  648.         (void) dup2(pipein[0], 0);
  649. #else
  650.         (void) close(0);
  651.         (void) dup(pipein[0]);
  652. #endif
  653.         (void) close(pipein[0]);
  654.         (void) close(pipein[1]);
  655.     }
  656.     else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
  657. #ifdef __MINT__
  658.         int fd = open(_PATH_DEVNULL, O_RDONLY);
  659.         (void)dup2(fd, 0);
  660.         (void)close(fd);
  661. #else
  662.         (void) close(0);
  663.         (void) open(_PATH_DEVNULL, O_RDONLY);
  664. #endif
  665.     }
  666.     else {
  667. #ifdef __MINT__
  668.         (void) dup2(OLDSTD, 0);
  669. #else
  670.         (void) close(0);
  671.         (void) dup(OLDSTD);
  672. #endif
  673. #ifdef FIOCLEX
  674. # ifdef CLEX_DUPS
  675.         /*
  676.          * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved
  677.          * across dup()s, so we have to UNSET it here or else we get a
  678.          * command with NO stdin, stdout, or stderr at all (a bad thing
  679.          * indeed)
  680.          */
  681.         (void) ioctl(0, FIONCLEX, NULL);
  682. # endif /* CLEX_DUPS */
  683. #endif /* FIONCLEX */
  684.     }
  685.     }
  686.     if (cp = t->t_drit) {
  687.     char    tmp[MAXPATHLEN+1];
  688.  
  689.     cp = globone(dp = Dfix1(cp), G_IGNORE);
  690.     (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
  691.     tmp[MAXPATHLEN] = '\0';
  692.     xfree((ptr_t) dp);
  693.     xfree((ptr_t) cp);
  694.     /*
  695.      * so > /dev/std{out,err} work
  696.      */
  697.     (void) dcopy(SHOUT, 1);
  698.     (void) dcopy(SHDIAG, 2);
  699.     if ((flags & F_APPEND) &&
  700. #ifdef O_APPEND
  701.         (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0);
  702. #else /* !O_APPEND */
  703.         (fd = open(tmp, O_WRONLY)) >= 0)
  704.         (void) lseek(1, (off_t) 0, L_XTND);
  705. #endif /* O_APPEND */
  706.     else {
  707.         if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
  708.         if (flags & F_APPEND)
  709.             stderror(ERR_SYSTEM, tmp, strerror(errno));
  710.         chkclob(tmp);
  711.         }
  712.         if ((fd = creat(tmp, 0666)) < 0)
  713.         stderror(ERR_SYSTEM, tmp, strerror(errno));
  714.     }
  715.     (void) dmove(fd, 1);
  716.     is1atty = isatty(1);
  717.     }
  718.     else if (flags & F_PIPEOUT) {
  719. #ifdef __MINT__
  720.     (void) dup2(pipeout[1], 1);
  721. #else
  722.     (void) close(1);
  723.     (void) dup(pipeout[1]);
  724. #endif
  725.     is1atty = 0;
  726.     }
  727.     else {
  728. #ifdef __MINT__
  729.     (void) dup2(SHOUT, 1);
  730. #else
  731.     (void) close(1);
  732.     (void) dup(SHOUT);
  733. #endif
  734.     is1atty = isoutatty;
  735. #ifdef FIOCLEX
  736. # ifdef CLEX_DUPS
  737.     (void) ioctl(1, FIONCLEX, NULL);
  738. # endif /* CLEX_DUPS */
  739. #endif /* FIONCLEX */
  740.     }
  741.  
  742.     (void) close(2);
  743.     if (flags & F_STDERR) {
  744. #ifdef __MINT__
  745.     (void) dup2(1, 2);
  746. #else
  747.     (void) dup(1);
  748. #endif
  749.     is2atty = is1atty;
  750.     }
  751.     else {
  752. #ifdef __MINT__
  753.     (void) dup2(SHDIAG, 2);
  754. #else
  755.     (void) dup(SHDIAG);
  756. #endif
  757.     is2atty = isdiagatty;
  758. #ifdef FIOCLEX
  759. # ifdef CLEX_DUPS
  760.     (void) ioctl(2, FIONCLEX, NULL);
  761. # endif /* CLEX_DUPS */
  762. #endif /* FIONCLEX */
  763.     }
  764.     didfds = 1;
  765. }
  766.  
  767. void
  768. mypipe(pv)
  769.     register int *pv;
  770. {
  771.  
  772.     if (pipe(pv) < 0)
  773.     goto oops;
  774.     pv[0] = dmove(pv[0], -1);
  775.     pv[1] = dmove(pv[1], -1);
  776.     if (pv[0] >= 0 && pv[1] >= 0)
  777.     return;
  778. oops:
  779.     stderror(ERR_PIPE);
  780. }
  781.  
  782. static void
  783. chkclob(cp)
  784.     register char *cp;
  785. {
  786.     struct stat stb;
  787.  
  788.     if (stat(cp, &stb) < 0)
  789.     return;
  790.     if (S_ISCHR(stb.st_mode))
  791.     return;
  792.     stderror(ERR_EXISTS, cp);
  793. }
  794.